#include "protocolmanager.h"
#include <QDebug>
#include <QDBusConnectionInterface>
#include <QCoreApplication>
#include "dbusproperties.h"
#include "statusnotifieritemsource.h"
#include "statusnotifierwatcher.h"
#include <QSessionManager>
#include "xcbutilss.h"
#include <QStandardItem>
#include "systemtraydaemonservice.h"

#define WATCHER_SERVICE_NAME "org.kde.StatusNotifierWatcher"
#define WATCHER_SERVICE_PATH "/StatusNotifierWatcher"

#if 1  //测试代码
    uint count = 0;
#endif

namespace Xcb {
    Xcb::Atoms* atoms;
}
ProtocolManager::ProtocolManager() :
  m_statusNotifierWatcher(nullptr),
  m_xembedToSni(nullptr)
{
    //实例化数据模型
    m_dataModel = new StatusNotifierModel();
    qDebug()<<">>> 实例化数据模型 ";

    //实例化lib库
//    m_systemTrayManager = new SystemTrayManager(m_dataModel);

    init();

#if 0  //测试程序：测试输出数据模型信息
    QTimer::singleShot(5000,this,[=]{
        qDebug()<<"===== 测试程序";
        qDebug()<<"===== count :"<<count;
        //打印数据
        int rowCount = m_dataModel->rowCount();
        int columnCount = m_dataModel->columnCount();
        qDebug()<<"===== "<<rowCount<<"行  "<<columnCount<<"列";
        for (int row = 0; row < rowCount; ++row) {
            QStandardItem* item = m_dataModel->item(row);
            if (item) {
                qDebug()<<"=====Id "<<item->data(StatusNotifierModel::Role::Id).toString();
                qDebug()<<"=====WindowId "<<item->data(StatusNotifierModel::Role::WindowId).toUInt();
                qDebug()<<"=====Category "<<item->data(StatusNotifierModel::Role::Category).toString();
                qDebug()<<"=====Status "<<item->data(StatusNotifierModel::Role::Status).toString();
                qDebug()<<"=====Title "<<item->data(StatusNotifierModel::Role::Title).toString();
                qDebug()<<"=====ToolTipTitle "<<item->data(StatusNotifierModel::Role::ToolTipTitle).toString();
                qDebug()<<"=====IconName "<<item->data(StatusNotifierModel::Role::IconName).toString();
                qDebug()<<"=====AttentionIconName "<<item->data(StatusNotifierModel::Role::AttentionIconName).toString();
                qDebug()<<"=====AttentionMovieName "<<item->data(StatusNotifierModel::Role::AttentionMovieName).toString();
            }
        }
    });
#endif
}

ProtocolManager::~ProtocolManager()
{
    QDBusConnection::sessionBus().unregisterService(WATCHER_SERVICE_NAME);
    QDBusConnection::sessionBus().unregisterService(m_hostServiceName);
    if(m_dataModel) {
        m_dataModel->deleteLater();
        m_dataModel = nullptr;
    }
    delete Xcb::atoms;
}

void ProtocolManager::init()
{
    if (QDBusConnection::sessionBus().isConnected()) {
        //注册 StatusNotifierHost 服务
        m_hostServiceName = "org.kde.StatusNotifierHost-" + QString::number(QCoreApplication::applicationPid());
        QDBusConnection::sessionBus().registerService(m_hostServiceName);
        qDebug()<<">>>>> 注册 StatusNotifierHost";
        //监控 StatusNotifierWatcher 服务
        QDBusServiceWatcher *watcher = new QDBusServiceWatcher(WATCHER_SERVICE_NAME, QDBusConnection::sessionBus(),
                                                               QDBusServiceWatcher::WatchForOwnerChange, this);
        connect(watcher, &QDBusServiceWatcher::serviceOwnerChanged,
                this, &ProtocolManager::serviceChange);
        qDebug()<<">>>>> 监控 StatusNotifierWatcher 服务";
        //注册 StatusNotifierWatcher 服务
        m_statusNotifierWatcherService = new StatusNotifierWatcher();

        //测试
        qDebug()<<"000000000000000000";
        SystemTrayDaemonService daemonService;
        qDebug()<<"1111111111111";

        registerWatcher(WATCHER_SERVICE_NAME);
        qDebug()<<">>>>> 注册 StatusNotifierWatcher 服务";
    }

#if 0
    //???判断一下是否是纯wayland环境，wayland环境下xembed无效，但是无法区分是x-wayland还是纯wayland
    //启动 xEmbed转SNI 服务
    //xEmbed转SNI服务必须在org.kde.StatusNotifierWatcher服务之后启动，
    //防止应用在ukui-panel之前启动时仍然可以检测到tray avliable
    qputenv("QT_QPA_PLATFORM", "xcb");
//        QGuiApplication::setDesktopSettingsAware(false);
//        QApplication app(argc, argv);
//        if (!KWindowSystem::isPlatformX11()) {
//            qFatal("xembed-sni-proxy is only useful XCB. Aborting");
//        }
//        auto disableSessionManagement = [](QSessionManager &sm) {
//            sm.setRestartHint(QSessionManager::RestartNever);
//        };
//        QObject::connect(&app, &QGuiApplication::commitDataRequest, disableSessionManagement);
//        QObject::connect(&app, &QGuiApplication::saveStateRequest, disableSessionManagement);
//        app.setQuitOnLastWindowClosed(false);
    Xcb::atoms = new Xcb::Atoms();
    m_xembedToSni = new SniXembedProxy(this);
//        auto rc = app.exec();
//        delete Xcb::atoms;
//    Xcb::atoms = nullptr;
    qDebug()<<">>>>> 启动 xEmbed转SNI 服务";
#endif
}

void ProtocolManager::registerWatcher(const QString& service)
{
    //qCDebug(DATAENGINE_SNI)<<"service appeared"<<service;
    if(service == WATCHER_SERVICE_NAME) {
        delete m_statusNotifierWatcher;

        m_statusNotifierWatcher = new org::kde::StatusNotifierWatcher(WATCHER_SERVICE_NAME,
                                                                      WATCHER_SERVICE_PATH,
                                                                      QDBusConnection::sessionBus());
        if (m_statusNotifierWatcher->isValid()) {
            m_statusNotifierWatcher->call(QDBus::NoBlock, QStringLiteral("RegisterStatusNotifierHost"), m_hostServiceName);

            OrgFreedesktopDBusPropertiesInterface propetriesIface(m_statusNotifierWatcher->service(),
                                                                  m_statusNotifierWatcher->path(),
                                                                  m_statusNotifierWatcher->connection());
            //??? 这几行不是很明白
            //获取所有Item服务
            QDBusPendingReply<QDBusVariant> pendingItems = propetriesIface.Get(m_statusNotifierWatcher->interface(),
                                                                               "RegisteredStatusNotifierItems");
            QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingItems, this);
            connect(watcher, &QDBusPendingCallWatcher::finished, this, [=]() {
                watcher->deleteLater();
                QDBusReply<QDBusVariant> reply = *watcher;
                QStringList registeredItems = reply.value().variant().toStringList();
                foreach (const QString &service, registeredItems) {
                    newItem(service);
                }
            });

            connect(m_statusNotifierWatcher, &OrgKdeStatusNotifierWatcherInterface::StatusNotifierItemRegistered,
                    this, &ProtocolManager::itemServiceRegistered);
            connect(m_statusNotifierWatcher, &OrgKdeStatusNotifierWatcherInterface::StatusNotifierItemUnregistered,
                    this, &ProtocolManager::itemServiceUnregistered);
        } else {
            qCritical()<<"ProtocolManager::StatusNotifierWatcher is invalid!";
            delete m_statusNotifierWatcher;
            m_statusNotifierWatcher = nullptr;
        }
    }
}

void ProtocolManager::serviceChange(const QString& name, const QString& oldOwner, const QString& newOwner)
{
    qDebug()<< "Service " << name << "status change, old owner:" << oldOwner << " new owner:" << newOwner;
    if (newOwner.isEmpty()) {
        unregisterWatcher(name);
    } else if (oldOwner.isEmpty()) {
        registerWatcher(name);
    }
}

void ProtocolManager::unregisterWatcher(const QString& service)
{
    if (service == WATCHER_SERVICE_NAME) {
        qCritical()<<"ProtocolManager: QDBusServiceWatcher Unregistered "<< WATCHER_SERVICE_NAME;
        disconnect(m_statusNotifierWatcher, &OrgKdeStatusNotifierWatcherInterface::StatusNotifierItemRegistered,
                   this, &ProtocolManager::itemServiceRegistered);
        disconnect(m_statusNotifierWatcher, &OrgKdeStatusNotifierWatcherInterface::StatusNotifierItemUnregistered,
                   this, &ProtocolManager::itemServiceUnregistered);

        //StatusNotifierWatcher服务注销时必须清空数据模型中的所有数据，防止StatusNotifierWatcher重新注册时模型中出现双份数据
        m_dataModel->removeAllSources();

        delete m_statusNotifierWatcher;
        m_statusNotifierWatcher = nullptr;
    }
}

void ProtocolManager::itemServiceRegistered(const QString &service)
{
    qInfo()<<"ProtocolManager: service Registered "<<service;
    newItem(service);
}

void ProtocolManager::itemServiceUnregistered(const QString &service)
{
    qInfo()<<"ProtocolManager: service Unregistered "<<service;
    //从StatusNotifierModel中删除Item
    m_dataModel->removeSource(service);
}

void ProtocolManager::newItem(const QString &service)
{
//    qDebug()<<">>>>> ProtocolManager::newItem :"<<service;
    StatusNotifierItemSource *itemSource = new StatusNotifierItemSource(service, this);
    count++;
    qDebug()<<"ProtocolManager:加入数据模型 "<<service;
    m_dataModel->addSource(service, itemSource);
}
